home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-06-30 | 17.5 KB | 772 lines | [TEXT/CWIE] |
- /*
- File: TApplication.cp
-
- Contains: TApplication: a class for applications with no document
-
- Written by: Arno Gourdol
-
- Copyright: © 1993-1996 by Apple Computer, Inc., all rights reserved.
-
-
- */
-
-
- #include "TApplication.h"
-
- #include <ToolUtils.h>
- #include <Dialogs.h>
- #include <Devices.h>
- #include <Menus.h>
- #include <Gestalt.h>
- #include <Scrap.h>
- #include <QDOffscreen.h>
- #include <LowMem.h>
- #include <DiskInit.h>
- #include <SegLoad.h> // For ExitToShell
- #include <TextEdit.h>
- #include <Processes.h>
-
- #include "assert.h"
- #include "macros.h"
-
- //
- // Menu resources
- //
- enum
- {
- kMainMenuBar = 128, // Menu bar of the application
- kAppleMenu = 128, // Apple menu
- kAboutMenuItem = 1,
-
- kFileMenu = 129, // File menu
- kCloseMenuItem = 1,
- kQuitMenuItem = 3,
-
- kEditMenu = 130, // Edit menu
- kUndoMenuItem = 1,
- kCutMenuItem = 3,
- kCopyMenuItem = 4,
- kPasteMenuItem = 5,
- kClearMenuItem = 6
- };
-
- //
- // Window, dialogs resources
- //
- enum
- {
- kAboutBoxDialog = 128 // Resource ID for About box alert
- };
-
- //
- // Result of GetScrapContent
- //
- #define kScrapHasText (1<<0)
- #define kScrapHasPict (1<<1)
- #define kScrapHasSound (1<<2)
- #define kScrapHasMovie (1<<3)
- #define kScrapHasUnknown (1<<8)
-
- /* Each item in the scrap begins with a resource type and length, followed
- by some variable-length data. This data structure is used to parse
- the scrap items. */
-
- typedef struct
- {
- ResType scrapType;
- long scrapLength;
- char scrapData[2];
- } ScrapItem, * ScrapItemPtr;
-
-
- // Template for the 'WIND' resource ??? Not used
- typedef struct
- {
- Rect boundsRect;
- short procID;
- short visible;
- short goAwayFlag;
- long refCon;
- char title[2];
- } WindowTemplate, *WindowTemplatePtr, **WindowTemplateHandle;
-
-
- TApplication* TApplication::gApplication = NULL; // The running application
-
- unsigned long GetScrapContent(void); // Returns the content of the scrap (PICT, TEXT...)
-
-
-
- // --------------------------------------------------------------------
- // IdleProc
- // --------------------------------------------------------------------
- // Callback idle function
-
- pascal Boolean TApplication::IdleProc(EventRecord *event,
- long *sleep,
- RgnHandle *mouseRgn)
- {
- *mouseRgn = NULL;
-
- switch (event->what)
- {
- case nullEvent:
- *sleep = 0;
- break;
-
- case updateEvt:
- {
- WindowRef window = (WindowRef)event->message;
- CWindow* windowObject = CWindow::GetCWindow(window);
- if (windowObject != NULL)
- {
- SetPort(windowObject->GetGrafPtr());
- BeginUpdate(window);
- windowObject->DoUpdate(GetWindowPort(window)->visRgn); // The visRgn contains the region that needs to be updated
- EndUpdate(window);
- }
- }
- break;
-
- case activateEvt:
- {
- WindowRef window = (WindowRef)event->message;
- CWindow* windowObject = CWindow::GetCWindow(window);
- if (windowObject != NULL)
- {
- windowObject->WindowActivated(event->modifiers & activeFlag);
- }
- }
- break;
-
- case osEvt:
- if (((event->message >> 24) & 0xFF) == suspendResumeMessage)
- {
- gApplication->AppActivated((event->message & resumeFlag) != 0);
- // ??? Do I need to activate/deactivate the frontmost window too?
- }
- break;
-
- default:
- break;
- }
- return false;
- }
-
-
-
- // --------------------------------------------------------------------
- // TApplication
- // --------------------------------------------------------------------
- // Application constructor
-
- TApplication::TApplication(OSType signature) :
- fFinished(false),
- fActive(true),
- fSignature(signature),
- fSleepTime(60)
- {
- {
- // First thing to do: set the stack size
- long newLimit = (long)LMGetCurStackBase() - LMGetDefltStack();
-
- // Set the stack size to be at least the default stack size
- if ((long)GetApplLimit() > newLimit)
- SetApplLimit((Ptr)newLimit);
- }
-
- // Remember who you are Rasputine
- assert(gApplication == NULL); // Can only have on app running
- gApplication = this;
-
- // Voodoo incantation
- MaxApplZone();
-
- MoreMasters();
- MoreMasters();
-
- InitGraf(&qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(NULL);
- InitCursor(); // Display the arrow cursor
- FlushEvents(everyEvent, 0); // Flush all events
-
- // Turn watch cursor on while initing app
- {
- CursHandle curH;
- if (NULL != (curH = GetCursor(watchCursor)))
- SetCursor(*curH);
- }
-
- // Read in the menu bar
- {
- Handle menuBar = GetNewMBar(kMainMenuBar);
- if (menuBar == NULL)
- ExitToShell();
- SetMenuBar(menuBar);
- DisposeHandle(menuBar);
- }
-
- // Set-up the Apple menu
- AppendResMenu(GetMenuHandle(kAppleMenu), 'DRVR'); // Add content of the Apple Menu to this menu
- }
-
-
-
- // --------------------------------------------------------------------
- // ~TApplication
- // --------------------------------------------------------------------
- // Application destructor
-
- TApplication::~TApplication()
- {
-
- }
-
-
-
- // --------------------------------------------------------------------
- // Run
- // --------------------------------------------------------------------
- // Start running the application
-
- void TApplication::Run(void)
- {
- DrawMenuBar(); // Draw Mr. Menu Bar.
-
- MenusWillShow(); // Enable items appropriately
-
- InitCursor(); // Show the cursor
-
- MainEventLoop(); // Process incoming events
- }
-
-
-
- // --------------------------------------------------------------------
- // MainEventLoop
- // --------------------------------------------------------------------
-
- void TApplication::MainEventLoop(void)
- {
- while (!fFinished)
- {
- EventRecord event;
-
- if (!WaitNextEvent(everyEvent, &event, fSleepTime, NULL))
- event.what = nullEvent;
- Event(event);
- }
- }
-
-
-
- // --------------------------------------------------------------------
- // Event
- // --------------------------------------------------------------------
- // Handles an event. Dispatch to a window if appropriate.
-
- void TApplication::Event(const EventRecord& event)
- {
- {
- // Decides which window is this event targetted at, if any
- CWindow* windowObject;
- if (event.what == updateEvt)
- windowObject = CWindow::GetCWindow((WindowRef) event.message); // (-)
- else
- windowObject = CWindow::GetCWindow(FrontWindow());
-
- if (windowObject != NULL)
- {
- // Let the window filter the event
- TDrawContext drawContext(windowObject->GetGrafPtr());
- if (drawContext.Lock())
- {
- Boolean eventHandled = windowObject->FilterEvent(event);
- drawContext.Unlock();
- if (eventHandled)
- return;
- }
- }
- }
-
- switch (event.what)
- {
- case nullEvent:
- Pulse();
- break;
- case mouseDown:
- {
- short part; // Code indicating where the click occured
- WindowRef window;
- CWindow* windowObject;
- part = FindWindow(event.where, &window);
- windowObject = CWindow::GetCWindow(window);
-
- switch (part)
- {
- case inMenuBar:
- // Call MenusWillShow() BEFORE MenuSelect()
- MenusWillShow(); // Update the menu items (enable/disable)
- /*if (window != NULL)
- window->MenusWillShow();
- */
- // Process the command
-
- HandleMenuCommand(MenuSelect(event.where)); break;
-
- case inSysWindow:
- SystemClick(&event, window);// Click in a "system" window (DA...)
- break;
-
- case inContent:
- {
- if (windowObject != NULL)
- {
- SetPort(windowObject->GetGrafPtr());
- ClipRect(&windowObject->GetGrafPtr()->portRect); // ??? Use Frame()
- windowObject->MouseDown(event);
- }
- }
- break;
-
- case inDrag:
- {
- DragWindow(window, event.where,
- CRect(-32000, -32000, 32000, 32000));
- if (windowObject != NULL)
- windowObject->FrameMoved(
- CPoint(*(Point*)&windowObject->
- GetGrafPtr()->portRect.left));
- }
- break;
-
- case inGrow:
- if (windowObject != NULL)
- {
- long growSize;
- // ??? Should use info from the window class
- CRect limitRect(100, 100, 1000, 1000) ;
- CRect windowRect;
-
- growSize = GrowWindow(window, event.where,
- limitRect);
-
- if (growSize != 0)
- windowObject->ResizeTo(LowWord(growSize),
- HighWord(growSize));
- }
- break;
-
- case inGoAway:
- if (windowObject != NULL &&
- TrackGoAway(window, event.where))
- {
- if (windowObject->CloseRequested())
- windowObject->Close();
- }
- break;
-
- case inZoomIn:
- case inZoomOut:
- if (windowObject != NULL &&
- TrackBox(window, event.where, part))
- {
- windowObject->Zoom(part == inZoomOut);
- }
- break;
- }
- }
- break;
-
- case keyDown:
- if (event.modifiers & cmdKey) // Command key down
- {
- // Update the menu items (enable/disable)
- MenusWillShow();
- // Call MenusWillShow() BEFORE MenuKey()
- // Process the commands
- HandleMenuCommand(MenuKey(
- (char)(event.message & charCodeMask)));
- }
- break;
-
- case diskEvt:
- {
- if (event.message >> 16)
- {
- Point where = {-1, -1};
- (void) DIBadMount(where, event.message);
- }
- };
- break;
-
- case updateEvt:
- {
- CWindow* windowObject;
- WindowRef window = (WindowRef)event.message;
- windowObject = CWindow::GetCWindow(window);
- if (windowObject != NULL)
- {
- SetPort(windowObject->GetGrafPtr());
- BeginUpdate(window);
- // The visRgn contains the region that needs to be updated
- windowObject->DoUpdate(
- windowObject->GetGrafPtr()->visRgn);
- EndUpdate(window);
- }
- }
- break;
-
- case activateEvt:
- {
- CWindow* windowObject;
- WindowRef window = (WindowRef)event.message;
- windowObject = CWindow::GetCWindow(window);
- if (windowObject != NULL)
- windowObject->WindowActivated(event.modifiers &
- activeFlag);
- }
- break;
-
- case osEvt:
- switch ((event.message & osEvtMessageMask) >> 24)
- {
- case mouseMovedMessage:
- break;
-
- case suspendResumeMessage:
- AppActivated((event.message & resumeFlag) != 0);
- // ??? Change the sleep time
- break;
- }
- break;
-
- case kHighLevelEvent:
- (void)AEProcessAppleEvent(&event);
- break;
-
- default:
- break;
- }
- }
-
-
-
- // --------------------------------------------------------------------
- // MenusWillShow
- // --------------------------------------------------------------------
- // Hook function called before the menus get displayed.
- // A chance to enable/disable menus
-
- void TApplication::MenusWillShow(void)
- {
- CWindow* windowObject = CWindow::GetCWindow(FrontWindow());
- if (windowObject != NULL)
- {
- windowObject->MenusWillShow();
- }
- }
-
-
-
- // --------------------------------------------------------------------
- // Pulse
- // --------------------------------------------------------------------
- // Idle time...
-
- void TApplication::Pulse(void)
- {
- for (CWindow* window = CWindow::GetFirstWindow();
- window != NULL; window = window->GetNextWindow())
- {
- window->Pulse();
- }
- }
-
-
-
- // --------------------------------------------------------------------
- // AppActivated
- // --------------------------------------------------------------------
- // Hook function called when the application is activated or
- // deactivated.
-
- void TApplication::AppActivated(Boolean active)
- {
- fActive = active;
- }
-
-
-
- // --------------------------------------------------------------------
- // Event
- // --------------------------------------------------------------------
- // Hook function called when an AppleEvent is received.
-
- OSErr TApplication::Event(AppleEvent* messagein,
- AppleEvent* reply,
- OSType eventID)
- {
- #pragma unused(messagein)
- #pragma unused(reply)
-
- OSErr result = noErr;
-
- switch (eventID)
- {
- case kAEOpenApplication:
- break;
-
- case kAEQuitApplication:
- if (QuitRequested())
- {
- Quit();
- }
- else
- {
- result = userCanceledErr;
- }
- break;
-
- case kAEOpenDocuments:
- // Fall in kAEPrintDocuments
- case kAEPrintDocuments:
- // Fall in default case
- default:
- result = errAEEventNotHandled;
- }
-
- return result;
- }
-
-
-
- // --------------------------------------------------------------------
- // HandleAppleEvent
- // --------------------------------------------------------------------
- // Static allback function called when an Apple Event is received.
-
- pascal OSErr TApplication::HandleAppleEvent(AppleEvent* messagein,
- AppleEvent* reply,
- OSType eventID)
- {
- // This static method is just a dispatcher to a virtual method (Event)
- // that can be overriden by subclasses.
- return gApplication->Event(messagein, reply, eventID);
- }
-
-
-
- // --------------------------------------------------------------------
- // InitAppleEvents
- // --------------------------------------------------------------------
- // Function called to initialize the Apple Event handlers.
-
- void TApplication::InitAppleEvents(void)
- {
- /* The following series of calls installs all our AppleEvent Handlers.
- * These handlers are added to the application event handler list that
- * the AppleEvent manager maintains. So, whenever an AppleEvent happens
- * and we call AEProcessEvent, the AppleEvent manager will check our
- * list of handlers and dispatch to it if there is one.
- */
-
- if (fEnvironment.HasAppleEvent())
- {
- struct AEinstalls
- {
- AEEventClass eventClass;
- AEEventID eventID;
- };
- typedef struct AEinstalls AEinstalls;
-
- static AEinstalls handlers[] =
- {
- /* The four required AppleEvents. */
- { kCoreEventClass, kAEOpenApplication},
- { kCoreEventClass, kAEOpenDocuments },
- { kCoreEventClass, kAEQuitApplication },
- { kCoreEventClass, kAEPrintDocuments },
-
- };
-
- AEEventHandlerUPP upp = NewAEEventHandlerProc(HandleAppleEvent);
- for (int i = 0; i < ((sizeof(handlers) / sizeof(AEinstalls))); i++)
- {
- (void)AEInstallEventHandler(handlers[i].eventClass,
- handlers[i].eventID,
- upp,
- handlers[i].eventID, false);
- }
- }
- }
-
-
-
- // --------------------------------------------------------------------
- // HandleMenuCommand
- // --------------------------------------------------------------------
- // Function dispatching a menu selection to a menu handler.
-
- void TApplication::HandleMenuCommand(long menuResult)
- {
- short menu = HighWord(menuResult);
- short item = LowWord(menuResult);
-
- MenuCommand(menu, item);
-
- HiliteMenu(0);
- }
-
-
-
- // --------------------------------------------------------------------
- // MenuCommand
- // --------------------------------------------------------------------
- // Hook function called when a menu selection is made.
-
- Boolean TApplication::MenuCommand(short menu, short item)
- {
- Boolean result = false;
-
- switch (menu)
- {
- case kAppleMenu:
- {
- if (item == kAboutMenuItem)
- {
- AboutRequested();
- }
- else
- {
- // Open the desk accessory
- Str255 itemName;
- GetMenuItemText(GetMenuHandle(kAboutMenuItem),
- item, itemName);
- OpenDeskAcc(itemName);
- }
- result = true;
- };
- break;
-
- case kFileMenu:
- {
- // Items in the File menu are close and quit.
- if (QuitRequested())
- Quit();
- result = true;
- };
- break;
-
- case kEditMenu:
- {
- // Pass the command on to the Desk Manager
- if (SystemEdit(item - 1))
- result = true;
- }
- break;
- }
-
- return result;
- }
-
-
-
- // --------------------------------------------------------------------
- // AboutRequested
- // --------------------------------------------------------------------
- // Hook function called to display an about box.
-
- void TApplication::AboutRequested(void)
- {
- // Display about box
- Alert(kAboutBoxDialog, NULL);
- }
-
-
-
- // --------------------------------------------------------------------
- // Quit
- // --------------------------------------------------------------------
- // Hook function called to quit.
-
- void TApplication::Quit(void)
- {
- assert(!fFinished);
- fFinished = true;
- }
-
-
-
- // --------------------------------------------------------------------
- // QuitRequested
- // --------------------------------------------------------------------
- // Hook function called when the user ask to quit.
- // Returns true if really want to quit, or false to cancel.
-
- Boolean TApplication::QuitRequested(void)
- {
- return true;
- }
-
-
-
- // --------------------------------------------------------------------
- // GetScrapContent
- // --------------------------------------------------------------------
-
- unsigned long GetScrapContent(void)
- // Returns the content of the scrap (kHasText, kHasPict, etc...)
- {
- unsigned long result;
- long byteCount;
- long len;
- long resTypeCount;
- ScrapItemPtr sp;
- char sState;
-
- result = 0;
-
- LoadScrap(); /* make sure the scrap is in ram */
-
- if ((!LMGetScrapHandle()) || /* no scrap handle */
- (LMGetScrapState() <= 0) || /* bad scrap state */
- (!LMGetScrapSize())) /* nothing in scrap */
- {
- return 0; /* nothing to get */
- }
-
- sState = HGetState(LMGetScrapHandle()); /* get current state of scrap */
- HLock(LMGetScrapHandle()); /* lock it down */
-
- sp = (ScrapItemPtr)StripAddress(*LMGetScrapHandle());/* pointer to first item in scrap */
- resTypeCount = 0; /* no resources added yet */
- byteCount = 0; /* no bytes added yet */
-
- while (byteCount < LMGetScrapSize())
- /* loop over all items in scrap */
- {
- if (sp->scrapType == 'PICT')
- result |= kScrapHasPict;
- else if (sp->scrapType == 'TEXT')
- result |= kScrapHasText;
- else if (sp->scrapType == 'snd ')
- result |= kScrapHasSound;
- else if (sp->scrapType == 'moov')
- result |= kScrapHasMovie;
-
- len = (sizeof(ScrapItem) - 2 + sp->scrapLength + 1) & ~1;/* no. bytes used up by this resource (word aligned) */
- sp = (ScrapItemPtr)((long)sp + len);/* update pointer to next resource */
- byteCount += len; /* count no. bytes processed so far */
- resTypeCount++; /* another resource added */
- }
-
- HSetState(LMGetScrapHandle(), sState); /* restore state of scrap */
-
- return result;
- }
-